﻿using AiBLSmartEdu.Module.AISlimmingAssistant.API.DTOs;
using AutoMapper;
using DocumentFormat.OpenXml.Office.SpreadSheetML.Y2023.MsForms;
using Domain.Entities;
using Domain.Entities.MentalHealth;
using Domain.Entities.SlimmingAssistants;
using FrameworkCore.Attributes;
using FrameworkCore.Constants;
using FrameworkCore.DI;
using FrameworkCore.Extensions;
using FrameworkCore.Helpers;
using FrameworkCore.Interfaces;
using FrameworkCore.Models;
using FrameworkCore.Repositories;
using Microsoft.Extensions.Configuration;
using OllamaSharp;
using OllamaSharp.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

#nullable disable

namespace AiBLSmartEdu.Module.AISlimmingAssistant.API.Services;

public class SlimmingAssistantServices : IScopedDependency
{
    private readonly IOllamaApiClient _ollama;
    private readonly IRepository<SlimmingAssistant> _repository;
    private readonly ICurrentUserService _currentUserService;
    private readonly IMapper _mapper;

    public SlimmingAssistantServices(
        IOllamaApiClient ollama,
        IRepository<SlimmingAssistant> repository,
        ICurrentUserService currentUserService,
        IMapper mapper)
    {
        _ollama = ollama;
        _repository = repository;
        _currentUserService = currentUserService;
        _mapper = mapper;
    }

    /// <summary>
    /// 分页查询
    /// </summary>
    /// <param name="filter">分页输入模型</param>
    /// <returns></returns>
    public async Task<PageResult<SlimmingAssistantOutputModel>> PageAsync(SlimmingAssistantPaginationFilter filter)
    {
        return (await _repository.GetOrderedQueryable(query =>
        {
            return query.OrderByDescending(o => o.Id)
            //.Where(x=>x.CreatedBy== _currentUserService.UserId)
            .WhereIf(!string.IsNullOrWhiteSpace(filter.Keyword), x => x.Referrals.Contains(filter.Keyword));

        }, filter).ProjectToPaginatedDataAsync<SlimmingAssistant, SlimmingAssistantOutputModel>(
            filter.PageNumber,
            filter.PageSize,
            _mapper.ConfigurationProvider
        )).ToPageList();
    }

    /// <summary>
    /// 填写信息
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task<long> CreateAsync(SlimmingAssistantCreateInputModel input)
    {
        var model = _mapper.Map<SlimmingAssistant>(input);
        await _repository.InsertAsync(model);
        return model.Id;
    }

    /// <summary>
    /// 删除信息
    /// </summary>
    /// <param name="id">唯一标识</param>
    /// <returns></returns>
    public async Task DeleteAsync(long id)
    {
        await _repository.DeleteAsync(x => x.Id == id);
    }

    /// <summary>
    /// 获取推荐
    /// </summary>
    public async Task<SlimmingAssistantOutputModel> GetReferralsAsync(long id) 
    {
        var data = await _repository.GetByIdAsync(id);
        ExceptionHelper.ThrowIfNull(data, "数据不存在");
        data.Referrals = await GenerateAsync(data);
        await _repository.UpdateAsync(data);
        return _mapper.Map<SlimmingAssistantOutputModel>(data);
    }

    public async Task<string> GenerateAsync(SlimmingAssistant input, CancellationToken cancellationToken = default)
    {
        var prompt = $@"# 角色设定
你是一位严谨的AI营养师，持有ACSM运动营养认证

# 数据输入模板**
[性别]={input.Gender.Value.ToString()}
[年龄]={input.Age}
[身高]={input.Height}cm
[体重]={input.Weight}kg 
[体脂率结果]={BodyFatAnalysis.Calculate(input.Gender.Value, input.Age.Value, input.Weight.Value, input.Height.Value)}
[目标]=正常值 [忌口]=无

## 处理要求
1️⃣ **营养方案设计**
- 生成7日严格控卡食谱（1600±50kcal）
- 常量营养配比：碳水45%｜蛋白质30%｜脂肪25%
- 标注每餐关键营养素：
  - Ω-3含量（mg）及来源类型
  - 膳食纤维含量（g）及可溶/不可溶比例
- 抗炎指数评级：⭐️(每增加0.5抗炎系数加⭐️)

2️⃣ **食材采购方案**
- 预算控制：￥200/周（±10%浮动）
- 标注优选渠道：超市常规区/生鲜区/冷冻区
- 提示当季替代食材（成本下降30%选项）

# 输出markdown格式";

        var generateRequest = new GenerateRequest()
        {
            Model = "qwen:14b",
            //Format = "string",
            Prompt = prompt
        };

        var responseBuilder = new StringBuilder();
        await foreach (var response in _ollama.GenerateAsync(generateRequest, cancellationToken))
        {
            if (response?.Response != null)
            {
                responseBuilder.Append(response.Response);
            }
        }

        return responseBuilder.ToString();
    }
}
